package client

import (
	"fmt"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	"specifica_video_manage/model"
	"sync"
)

var db *gorm.DB
var err error
var lock sync.Mutex

func init() {
	dst := "root:root@(localhost:3306)/specific_account?charset=utf8mb4&parseTime=True&loc=Local"
	db, err = gorm.Open("mysql", dst)
	if err != nil {
		fmt.Println("Client init catch error =", err)
	}
}

func InitDB() error {
	dst := "root:root@(localhost:3306)/specific_account?charset=utf8mb4&parseTime=True&loc=Local"

	db, err = gorm.Open("mysql", dst)
	if err != nil {
		fmt.Println("InitDB catch error =", err)
		return err
	}
	return nil
}

type MysqlTaskClient struct{}

func (m MysqlTaskClient) AutoMigrate() bool {
	flag := true
	err := InitDB()
	if err != nil {
		fmt.Println("migrate mysql table catch error =", err)
	}
	fmt.Println("start migrate SingleTaskModel")
	if err := db.AutoMigrate(&model.SingleTaskModel{}); err.Error != nil {
		fmt.Println("MysqlTaskClient.AutoMigrate model.GormSingleTask catch error:", err.Error)
		flag = false
	} else {
		fmt.Println("MysqlTaskClient.AutoMigrate model.GormSingleTask success!")
	}
	if err := db.AutoMigrate(&model.VideoModel{}); err.Error != nil {
		fmt.Println("MysqlTaskClient.AutoMigrate model.VideoModel catch error:", err.Error)
		flag = false
	} else {
		fmt.Println("MysqlTaskClient.AutoMigrate model.VideoModel success!")
	}
	if err := db.AutoMigrate(&model.AuthorModel{}); err.Error != nil {
		fmt.Println("MysqlTaskClient.AutoMigrate model.AuthorModel catch error:", err.Error)
		flag = false
	} else {
		fmt.Println("MysqlTaskClient.AutoMigrate model.AuthorModel success!")
	}
	if err := db.AutoMigrate(&model.UrlRecord{}); err.Error != nil {
		fmt.Println("MysqlTaskClient.AutoMigrate model.UrlRecord catch error:", err.Error)
		flag = false
	} else {
		fmt.Println("MysqlTaskClient.AutoMigrate model.UrlRecord success!")
	}

	return flag
}

func (m MysqlTaskClient) CreateTask(task *model.SingleTaskModel) error {
	if err := db.Create(&task).Error; err != nil {
		fmt.Println("MysqlTaskClient.CreateTask catch error =", err.Error())
		return err
	}
	return nil
}

func (m MysqlTaskClient) CreateVideo(video *model.VideoModel) error {
	lock.Lock()
	tx := db.Begin()
	newVideo := model.VideoModel{}
	tx.Where("vid = ? and platform = ?", video.Vid, video.Platform).First(&newVideo)
	if len(newVideo.Title) == 0 {
		// not in db
		err := tx.Create(&video).Error
		if err != nil {
			tx.Rollback()
			lock.Unlock()
			return err
		}
	}
	// already in db, do upload
	err := tx.Model(&video).Where("vid = ? and platform = ?", video.Vid, video.Platform).Update(&video).Error
	if err != nil {
		tx.Rollback()
		lock.Unlock()
		return err
	}
	tx.Commit()
	lock.Unlock()
	return nil
}

func (m MysqlTaskClient) CreateAuthor(author *model.AuthorModel) error {
	lock.Lock()
	tx := db.Begin()
	newAuthor := model.AuthorModel{}
	tx.Where("author_id = ? and platform = ?", author.AuthorId, author.Platform).First(&newAuthor)
	if len(newAuthor.NickName) == 0 {
		fmt.Println("not in db, create")
		// not in db, create
		//fmt.Printf("author info = %#v", author)
		result := tx.Create(&author)
		//fmt.Println("create author error:", err)
		if result.Error != nil {
			fmt.Println("create author RowsAffected =", result.RowsAffected)
			tx.Rollback()
			lock.Unlock()
			return result.Error
		}
	}
	fmt.Println("already in db, update ")
	//fmt.Printf("author info = %#v", author)
	result := tx.Model(&author).Where("author_id = ? and platform = ?", author.AuthorId, author.Platform).Update(&author).Error
	if result.Error != nil {
		fmt.Println(result.Error())
		tx.Rollback()
		lock.Unlock()
		return result
	}
	tx.Commit()
	lock.Unlock()
	return nil

}

func (m MysqlTaskClient) QueryRecordUrl(url string) bool {
	queryUrl := model.UrlRecord{}
	db.Where(&model.UrlRecord{Url: url}).First(&queryUrl)
	//fmt.Println("QueryRecordUrl :", queryUrl)
	//fmt.Println(queryUrl.Url, len(queryUrl.Url))
	if len(queryUrl.Url) > 0 {
		fmt.Println("url already in record", url)
		return true
	}
	return false
}

func (m MysqlTaskClient) CreateUrl(recordInfo *model.UrlRecord) {
	queryUrl := model.UrlRecord{}
	db.Where(recordInfo).First(&queryUrl)
	if len(queryUrl.Url) > 0 {
		fmt.Println("url already in record")
	} else {
		fmt.Println("create new record")
		db.Save(recordInfo)
	}
}

func (m MysqlTaskClient) GetUnStartJob() *model.SingleTaskModel {
	queryTask := model.SingleTaskModel{}
	lock.Lock()
	tx := db.Begin()
	tx.Model(&model.SingleTaskModel{}).Where("state = ?", 0).First(&queryTask)
	fmt.Println("queryTask:", queryTask)
	if len(queryTask.Account) > 0 {
		// find a fresh job
		// update job state
		queryTask.State = 1
		result := tx.Model(&model.SingleTaskModel{}).Where("id = ?", queryTask.Model.ID).Update(&queryTask)

		fmt.Println("result.RowsAffected=", result.RowsAffected)
		fmt.Printf("%#v", result.Error)
		if result.Error == nil {
			// error is nil, success
			tx.Commit()
			lock.Unlock()
			return &queryTask
		} else {
			tx.Rollback()
			lock.Unlock()
			return nil
		}

	} else {
		// empty job queue
		fmt.Println("queryTask.Account.len = 0")
		tx.Rollback()
		lock.Unlock()
		return nil
	}
}

func (m MysqlTaskClient) UpdateJobState(updateState *model.UpdateUrlState) bool {
	//fmt.Println("func UpdateJobState")
	lock.Lock()
	tx := db.Begin()
	result := tx.Model(&model.SingleTaskModel{}).Where("id = ? and task_id = ?", updateState.Id, updateState.TaskId).Update(&updateState)
	fmt.Println("result.RowsAffected:", result.RowsAffected)
	if result.RowsAffected > 0 {
		// update state success
		//fmt.Println("update job state success!")
		tx.Commit()
		lock.Unlock()
		return true
	} else {
		//fmt.Println("update job state catch err:", result.Error)
		tx.Rollback()
		lock.Unlock()
		return false
	}

}
